﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{

    public partial class Form2 : Form
    {

        //private const string getProxyUrl = "http://www.66ip.cn/nmtq.php?getnum=1000&isp=0&anonymoustype=0&start=&ports=&export=&ipaddress=&area=1&proxytype=0&api=66ip";
        //private const string getProxyUrl = "http://www.xicidaili.com/wt/1";
        private const string getProxyUrl = "http://www.yun-daili.com/free.asp?stype={0}&page={1}";


        private HttpSender httpSender = new HttpSender();

        private Object successLocker = new object();
        private Object failedLocker = new object();

        List<ProxyInfo> proxyList = new List<ProxyInfo>();

        ResultDelegate resultDelegate;


        public Form2()
        {
            InitializeComponent();
            resultDelegate = new ResultDelegate(appendResult);
            httpSender.SetErrorInovker(resultDelegate);
        }

        private void Form2_Load(object sender, EventArgs e)
        {

        }

        private void btnGetProxy_Click(object sender, EventArgs e)
        {
            proxyList.Clear();
            int proxyNum;
            if (!int.TryParse(txtProxyNum.Text, out proxyNum))
            {
                MessageBox.Show("bad number");
                return;
            }
            string proxyUrl = string.Format(getProxyUrl, 1, 1);
            refreshProxy(proxyUrl, proxyNum);
            //richTxtContent.Text = body;
        }

        private void refreshProxy(string proxyUrl = null, int count = 200, int pageIndex = 1)
        {
            if (count < 1 || string.IsNullOrWhiteSpace(proxyUrl))
            {
                return;
            }


            httpSender.ResetProxy();
            var body = httpSender.get_Internet(getProxyUrl);
            if (string.IsNullOrWhiteSpace(body))
            {
                appendResult("Refresh proxy failed :(");
                return;
            }

            parseProxyList2(body);
            if (proxyList.Count < count)
            {
                string url = getNextProxy(pageIndex + 1);
                refreshProxy(url, count, pageIndex + 1);
            }
            else
            {
                appendResult("Refresh proxy success, num:{0}.", proxyList.Count);
            }
        }

        private string getNextProxy(int pageIndex)
        {
            return string.Format(getProxyUrl, 1, pageIndex);
        }

        private void parseProxyList(string body)
        {
            Regex reg = new Regex(@"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{1,5})");
            var matches = reg.Matches(body);
            string ip = null;
            int port = 0;
            foreach (Match item in matches)
            {
                ip = item.Groups[1].Value;
                if (!int.TryParse(item.Groups[2].Value, out port))
                {
                    continue;
                }
                proxyList.Add(new ProxyInfo(ip, port));
            }
        }

        private void parseProxyList2(string body)
        {
            Regex reg = new Regex(@"[^>]+?>\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s*<[^>]+>\s*[^>]+?>\s*(\d{1,5})\s*<");
            var matches = reg.Matches(body);
            string ip = null;
            int port = 0;
            foreach (Match item in matches)
            {
                ip = item.Groups[1].Value;
                if (!int.TryParse(item.Groups[2].Value, out port))
                {
                    continue;
                }
                proxyList.Add(new ProxyInfo(ip, port));
            }
        }




        private void btnAccess_Click(object sender, EventArgs e)
        {
            var url = txtUrl.Text;
            if (string.IsNullOrWhiteSpace(url))
            {
                MessageBox.Show("url error!");
                return;
            }

            if (proxyList == null || proxyList.Count == 0)
            {
                refreshProxy();
            }

            var proxies = proxyList.Select(p => new { p.IP, p.port }).AsParallel();

            Task task = new Task(() =>
            {

                int success = 0, failed = 0;
                proxies.ForAll((item) =>
                {
                    var www = new HttpSender();
                    www.SetErrorInovker(resultDelegate);
                    www.SetProxy(item.IP, item.port);
                    if (!string.IsNullOrWhiteSpace(www.get_Internet(url)))
                    {
                        lock (successLocker)
                        {
                            success++;
                        }
                        txtResut.Invoke(resultDelegate, string.Format("Access success,ip:{0},port:{1} :)", item.IP, item.port));
                    }
                    else
                    {
                        lock (successLocker)
                        {
                            failed++;
                        }
                        txtResut.Invoke(resultDelegate, string.Format("Access failed, ip:{0},port:{1} :(", item.IP, item.port));

                    }
                });
                txtResut.Invoke(resultDelegate, string.Format("Accesses were completed! total:{0},  success:{1}, failed:{2}.", proxyList.Count, success, failed));
            });
            task.Start();

        }

        public void appendResult(string formator, params object[] args)
        {
            appendResult(string.Format(formator, args));
        }




        public void appendResult(string result)
        {
            if (txtResut.InvokeRequired)
            {
                txtResut.Invoke(resultDelegate, result);
            }
            else
            {
                txtResut.AppendText("---> " + result);
                txtResut.AppendText(Environment.NewLine);
            }
        }
    }
}
